package com.wf.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wf.domain.Account;
import com.wf.domain.Bids;
import com.wf.domain.LoanTargets;
import com.wf.domain.SysUser;
import com.wf.mapper.AccountMapper;
import com.wf.mapper.BidsMapper;
import com.wf.mapper.LoanTargetsMapper;
import com.wf.service.BidsService;
import com.wf.service.LoanTargetsService;
import com.wf.utils.RedisUtil;
import com.wf.utils.RedissonLockUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@Service
public class BidsServiceImpl extends ServiceImpl<BidsMapper, Bids>
        implements BidsService {

    @Autowired
    private LoanTargetsService loanTargetsService;

    @Autowired
    AccountMapper accountMapper;

    @Autowired
    BidsMapper bidsMapper;
    @Autowired
    LoanTargetsMapper loanTargetsMapper;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    RedissonLockUtil redissonLockUtil;


    /**
     * 预热
     *
     * @param loanId
     */
    @Override
    public void preheat(String loanId) {
        LoanTargets loanTargets = loanTargetsMapper.selectById(loanId);

        Double investedAmount = loanTargets.getInvestedAmount();

        Double amount = loanTargets.getAmount();

        redisUtil.set("loan:bid:" + loanId + ":investedAmount", investedAmount);

        redisUtil.set("loan:bid:" + loanId + ":amount", amount);

    }

    @Override
    @Transactional
    public void bid(String targetId, String money) {

        String lockKey="bank:loan:loanTarget:" + targetId;
        redissonLockUtil.lock(lockKey);
        try {
            double aDouble = Double.parseDouble(money);
            // 1. 查询用户余额是否足够,如果不够，提示用户余额不足
            Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            Account account = null;
            Double balance = null;
            if (principal instanceof SysUser) {
                SysUser user = (SysUser) principal;
                String userId = user.getUserId();
                LambdaQueryWrapper<Account> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Account::getUserId, userId);
                account = accountMapper.selectOne(wrapper);
                balance = account.getBalance();
                if (balance < aDouble) {
                    throw new RuntimeException("余额不足");
                }
            } else {
                throw new RuntimeException("用户未登录");
            }

            // 2. 查询当前标的的已投金额，总金额
            //总金额
            Double amount = (Double) redisUtil.get("loan:bid:" + targetId + ":amount");
            // 已投金额
            Double investedAmount = (Double) redisUtil.get("loan:bid:" + targetId + ":investedAmount");

            if (aDouble > amount - investedAmount) {
                throw new RuntimeException("不能再投资了");
            }
            redisUtil.set("loan:bid:" + targetId + ":investedAmount", investedAmount + aDouble);

//        account.setBalance(balance - aDouble);
//        accountMapper.updateById(account);

            LoanTargets loanTargets = loanTargetsMapper.selectById(targetId);
            // 4. 更新标的信息表、投资记录表
            loanTargets.setInvestedAmount(investedAmount + aDouble);
            loanTargetsMapper.updateById(loanTargets);
            Bids bids = new Bids();
            bids.setBidAmount(aDouble);
            bids.setInvestorId(account.getUserId());
            bids.setTargetId(loanTargets.getTargetId());
            bids.setStatus("successful");
            bidsMapper.insert(bids);
            LambdaUpdateWrapper<Account> wrapper = new LambdaUpdateWrapper<>();
            wrapper.setSql("balance = balance-" + aDouble);
            accountMapper.update(account, wrapper);


        } finally {
            redissonLockUtil.unlock(lockKey);
        }


    }


}




